package dxbridge.model.impl;

import java.util.Arrays;


import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import dxbridge.model.IRecord;
import dxbridge.model.ITable;

/**
 * 
 * The <code>Record</code> class is a data model for one record in database.
 * here it only store the values of this record, and the handler to the
 * {@link Table}, which is the owner of this record. Keep in mind that
 * 
 */
public class Record implements IRecord {

    /**
     * Create a record
     * 
     * @param table
     * @param values
     */
    public Record(ITable table, String[] values) {
        this.table = table;
        this.values = values;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#getXPath()
     */
    public String getXPath() {
        // example: "//code_mstr[code_fldname=\"abd_conv1\"]"

        StringBuffer xpath = new StringBuffer();
        xpath.append(table.getXpath());
        xpath.append("[");
        String[] fields = table.getFieldNames();
        int[] keyIndex = table.getKeyIndex();

        for (int i = 0; i < keyIndex.length; i++) {
            String keyFieldName = fields[keyIndex[i]];
            xpath.append(keyFieldName).append("=");
            xpath.append("\"").append(values[keyIndex[i]]).append("\"");
            if (i + 1 < keyIndex.length) {
                xpath.append(" and ");
            }
        }
        xpath.append("]");

        return xpath.toString();

    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#isKeyFieldValuesEqual(model.impl.IRecord)
     */
    public boolean isKeyFieldValuesEqual(IRecord anotherRecord) {

        String[] anotherValues = anotherRecord.getValues();
        int[] keyIndex = table.getKeyIndex();
        for (int element : keyIndex) {
            if (values[element] == null) {
                if (anotherValues[element] == null) {
                    return true;
                }
                return false;
            }
            if (anotherValues[element] == null) {
                return false;
            }
            if (values[element].equals(anotherValues[element]) == false) {
                return false;
            }
        }
        return true;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object record) {

        IRecord anotherRecord = (IRecord) record;
        String[] anotherValues = anotherRecord.getValues();

        for (int i = 0; i < anotherValues.length; i++) {
            if (values[i] == null) {
                if (anotherValues[i] == null) {
                    continue;
                    // both is null , equals
                } else {
                    return false;
                }
            }
            if (anotherValues[i] == null) {
                return false;
            }

            if (values[i].equals(anotherValues[i]) == false) {
                return false;
            }
        }

        return true;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#toXMLElement()
     */
    public Element toXMLElement() {
        Element elementRecord = DocumentHelper.createElement(table
                .getTableName());
        String[] fieldNames = table.getFieldNames();
        for (int i = 0; i < fieldNames.length; i++) {
            if (values[i] != null) {
                Element t = DocumentHelper.createElement(fieldNames[i]);
                t.addText(values[i]);
                elementRecord.add(t);
            }
        }

        return elementRecord;

    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#getValueForField(java.lang.String)
     */
    public String getValueForField(String fieldName) {
        int index;
        index = table.getIndexOfField(fieldName);
        if (index != -1) {
            return values[index];
        }
        return null;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#getGNRString()
     */
    public String getGNRString() {
        StringBuffer sb = new StringBuffer("/");
        int[] keyIndex = this.table.getKeyIndex();
        for (int i = 0; i < keyIndex.length; i++) {
            sb.append(values[keyIndex[i]]);
            if (i + 1 < keyIndex.length) {
                sb.append(FIELD_SEPARATOR);
            }
        }
        return sb.toString();
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#getTable()
     */
    public ITable getTable() {
        return table;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#setTable(model.ITable)
     */
    public void setTable(ITable table) {
        this.table = table;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#getValues()
     */
    public String[] getValues() {
        return values;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#setValues(java.lang.String[])
     */
    public void setValues(String[] values) {
        this.values = values;
    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#printTest()
     */
    public void printTest() {
        System.out.println(String.format("===== Test Record ====="));
        System.out.println(String.format("Values: %s", Arrays
                .deepToString(values)));
        System.out.println(String.format("XPath: %s", getXPath()));
        System.out.println(String.format("XML Element: %s", toXMLElement()
                .asXML()));

    }

    /* (non-Javadoc)
     * @see model.impl.IRecord#toString()
     */
    @Override
    public String toString() {
        return Arrays.deepToString(values);
    }

    /**
     * Separator in gnr string.
     */
    private static final String FIELD_SEPARATOR = "/";

    /** Which table this record belong to */
    private ITable table;
    /** The values contains in record */
    private String[] values;

}
